﻿/*****************************************************
 * formMain                                          *
 * Made by Niklas Plüm (l4nm4n@users.sourceforge.net)*
 *****************************************************/

#region Imports
using System;
using System.Windows.Forms;
using System.Diagnostics;
using VisualPureBasicIDE.CoreGUI.Extensibility;
using VisualPureBasicIDE.CoreGUI.Properties;
using VisualPureBasicIDE.CoreGUI.SolutionManager;
using VisualPureBasicIDE.FormDesigner;
using WeifenLuo.WinFormsUI.Docking;
using VisualPureBasicIDE.PureBasic;

#endregion

namespace VisualPureBasicIDE.CoreGUI
{
    public partial class MainForm : Form
    {

        #region Fields
        private string _loadedProject;

        private delegate void SetStatusStripSettingsCallback();
        //private delegate void CloseActionProgressDialogCallback(formActionProgress ad);
        #endregion

        #region Properties

        public DockPanel DockPanel { get { return dockPanel; } }

        #endregion

        #region Helper methods

        /// <summary>
        /// This occurs when the plugin loader is finished
        /// </summary>
        /// <param name="tag">The IAsyncResult of the operation</param>
        private void PluginLoaderCallback(IAsyncResult tag)
        {
            if (tag.IsCompleted)
            {
                // only for thread safety
                SetStatusStripSettings();
            }
        }

        /// <summary>
        /// Sets the status strip settings (for safe multithreading)
        /// </summary>
        private void SetStatusStripSettings()
        {
            if (InvokeRequired)
            {
                // Invoke is required, waiting for callback...
                var d = new SetStatusStripSettingsCallback(SetStatusStripSettings);
                Invoke(d);
            }
            else
            {
                // Invoke isn't required, so let's set it!
                lock (toolStripProgressBarWorkerProgress)
                {
                    toolStripProgressBarWorkerProgress.Style = ProgressBarStyle.Marquee;
                    toolStripProgressBarWorkerProgress.Visible = false;
                    toolStripStatusLabelAction.Text = Translator.GetStringAndTranslate("strReady");
                }
            }
        }

        /// <summary>
        /// Compiles the current source and then runs it
        /// </summary>
        private void CompileAndRun()
        {
            if (dockPanel.ActiveDocument != null)
            {
                // Test code, hard coded

                try
                {
                    if (Settings.Default.CompilerExecutablePath.Length == 0) return;

                    compileAndRunToolStripMenuItem.Enabled = false;
                    toolStripButtonCompileAndRun.Enabled = false;
                    Application.DoEvents();

                    var codeComp = new CodeCompiler();
                    var compInfo = new CompilerInfo
                                       {
                                           CompilerExecutable = Settings.Default.CompilerExecutablePath,
                                           MainIcon = null,
                                           MainSourceFile =
                                               '"' +
                                               ((EditorForm) dockPanel.ActiveDocument.DockHandler.Form).InnerDocument.
                                                   Path + '"',
                                           XpSkinSupport = true
                                       };

                    codeComp.StartCompiling(compInfo, WindowManager.BuildOutputWindow.textBoxOutput);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, Translator.GetStringAndTranslate("strError"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                finally
                {
                    compileAndRunToolStripMenuItem.Enabled = true;
                    toolStripButtonCompileAndRun.Enabled = true;
                }
            }
        }

        internal ToolStripMenuItem CreatePluginMenuItem(IPlugin plugin)
        {
            return (ToolStripMenuItem)pluginActionsToolStripMenuItem.DropDownItems.Add(plugin.Name);
        }
        #endregion

        #region GUI event handlers
        /// <summary>
        /// The main constructor for this Windows.Forms.Form 
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            // Subscribe to "essential" signals (events)
            EventManager.ActivateRedo += StandardActions_ActivateRedo;
            EventManager.ActivateUndo += StandardActions_ActivateUndo;
            EventManager.DeactivateRedo += StandardActions_DeactivateRedo;
            EventManager.DeactivateUndo += StandardActions_DeactivateUndo;
        }

        /// <summary>
        /// The StandardActions_DeactivateUndo handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void StandardActions_DeactivateUndo(object sender, EventArgs e)
        {
            toolStripButtonUndo.Enabled = false;
            undoToolStripMenuItem.Enabled = false;
        }

        /// <summary>
        /// The StandardActions_DeactivateRedo handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void StandardActions_DeactivateRedo(object sender, EventArgs e)
        {
            toolStripButtonRedo.Enabled = false;
            redoToolStripMenuItem.Enabled = false;
        }

        /// <summary>
        /// The StandardActions_ActivateUndo handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void StandardActions_ActivateUndo(object sender, EventArgs e)
        {
            toolStripButtonUndo.Enabled = true;
            undoToolStripMenuItem.Enabled = true;
        }

        /// <summary>
        /// The StandardActions_ActivateRedo handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void StandardActions_ActivateRedo(object sender, EventArgs e)
        {
            toolStripButtonRedo.Enabled = true;
            redoToolStripMenuItem.Enabled = true;
        }

        private void pbSourceFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DocumentManager.NewSourceFile();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void pbSourceFileToolStripMenuItem2_Click(object sender, EventArgs e)
        {
            DocumentManager.OpenSourceFile();
        }

        private void newProjectWindowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show(Translator.GetStringAndTranslate("strNotImplementedFull"), Translator.GetStringAndTranslate("strNotImplemented"), MessageBoxButtons.OK,
                            MessageBoxIcon.Exclamation);
        }

        private void solutionManagerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.SolutionExplorer.DockPanel = dockPanel;
            WindowManager.SolutionExplorer.DockState = DockState.DockRight;
            WindowManager.SolutionExplorer.DockStateChanged += SolutionExplorer_DockStateChanged;
            WindowManager.SolutionExplorer.ActionRequest += SolutionExplorer_ActionRequest;
            WindowManager.SolutionExplorer.Show();
            //solutionManagerToolStripMenuItem.CheckState = CheckState.Checked;
        }

        private void SolutionExplorer_DockStateChanged(object sender, EventArgs e)
        {
            var isChecked = (WindowManager.SolutionExplorer.DockState != DockState.Hidden);
            solutionManagerToolStripMenuItem.CheckState = (isChecked ? CheckState.Checked : CheckState.Unchecked);
        }

        private static void SolutionExplorer_ActionRequest(object sender, SolutionActionEventArgs e)
        {
            if (e.Node == null) return;

            // NOTE: Some actions are already processed in SolutionTreeView (like IncludeInProject)
            switch (e.Action)
            {
                case SolutionTreeViewActions.ViewCode:
                case SolutionTreeViewActions.Open:
                    DocumentManager.OpenSourceFile(e.Node.Path);
                    break;

                case SolutionTreeViewActions.OpenInExplorer:
                    var process = new Process
                                      {
                                          StartInfo =
                                              {
                                                  Arguments = e.Node.Path,
                                                  FileName = "explorer.exe",
                                                  UseShellExecute = false
                                              }
                                      };
                     
                    process.Start();
                    break;
            }
        }

        private void formMain_Load(object sender, EventArgs e)
        {
            // TODO: Implement a generic window title manager (StatusManager, see below)
            _loadedProject = "(" + Translator.GetStringAndTranslate("strNoProjectLoaded") + ")";
            Text = _loadedProject + " - Visual PureBasic IDE";

            if (InvariantStrings.AdministratorRights) Text += " (Administrator)";

            WindowManager.AlignMainWindowToScreen();
            WindowManager.InitializeLayout();

            var invoker = new MethodInvoker(PluginManager.InstantiateAndLoadAllPlugins);
            toolStripProgressBarWorkerProgress.Style = ProgressBarStyle.Marquee;
            toolStripProgressBarWorkerProgress.Visible = true;
            invoker.BeginInvoke(PluginLoaderCallback, null);

            toolStripStatusLabelAction.Text = Translator.GetStringAndTranslate("strLoadingPlugins");
        }

        private void closeAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            for (var i = 0; i < Application.OpenForms.Count; i++)
            {
                if (Application.OpenForms[i].Text != "Visual PureBasic IDE SourceExplorer") continue;

                Application.OpenForms[i].Close();
                i--;
            }
        }

        private void timerResetStatusStrip_Tick(object sender, EventArgs e)
        {
            // TODO: Refactor to class (StatusManager or so ...)

            statusStripMain.Items[0].Text = Translator.GetStringAndTranslate("strReady");
            timerResetStatusStrip.Stop();
        }

        private void toolStripSplitButtonNew_ButtonClick(object sender, EventArgs e)
        {
            DocumentManager.NewSourceFile();
        }

        private void saveFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DocumentManager.SaveCurrentSourceFile();
        }

        private void toolStripButtonLoad_Click(object sender, EventArgs e)
        {
            DocumentManager.OpenSourceFile();
        }

        private void toolStripButtonSave_Click(object sender, EventArgs e)
        {
            DocumentManager.SaveCurrentSourceFile();
        }

        private void compilerMessagesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // TODO: This should accomplish the WindowManager itself
            WindowManager.BuildOutputWindow.DockPanel = dockPanel;
            WindowManager.BuildOutputWindow.Show();
        }

        private void objectInspektorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.ObjectInspector.DockPanel = dockPanel;
            WindowManager.ObjectInspector.DockState = DockState.DockRightAutoHide;
            WindowManager.ObjectInspector.Show();
        }

        private void gadgetListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.Toolbox.DockPanel = dockPanel;
            WindowManager.Toolbox.DockState = DockState.DockLeftAutoHide;
            WindowManager.Toolbox.Show();
        }

        private void debugShowDesignerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var designer = new Designer(WindowManager.ObjectInspector.propertyGrid, WindowManager.Toolbox.toolboxServiceImpl)
                               {DockPanel = dockPanel};
            designer.DockState = DockState.Document;
            designer.Show();
        }

        private void windowListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var windowList = new WindowListForm(dockPanel);
            windowList.ShowDialog();
        }

        private void powerConsoleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.Console.DockPanel = dockPanel;
            WindowManager.Console.DockState = DockState.DockBottom;
            WindowManager.Console.Show();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var myPreferences = new PreferencesForm{ApplyAlwaysEnabled = true};
            myPreferences.ShowDialog();
        }

        private void newPBSourceFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DocumentManager.NewSourceFile();
        }

        private void toolStripButtonCopy_Click(object sender, EventArgs e)
        {
            EventManager.OnCopyContent(sender, e);
        }

        private void toolStripButtonPaste_Click(object sender, EventArgs e)
        {
            EventManager.OnPasteContent(sender, e);
        }

        private void toolStripButtonUndo_Click(object sender, EventArgs e)
        {
            EventManager.OnUndoLastAction(sender, e);
        }

        private void toolStripButtonRedo_Click(object sender, EventArgs e)
        {
            EventManager.OnRedoLastAction(sender, e);
        }

        private void toolStripButtonCut_Click(object sender, EventArgs e)
        {
            EventManager.OnCutContent(sender, e);
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EventManager.OnUndoLastAction(sender, e);
        }

        private void redoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EventManager.OnRedoLastAction(sender, e);
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EventManager.OnCopyContent(sender, e);
        }

        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EventManager.OnPasteContent(sender, e);
        }

        private void toolStripButtonSaveAll_Click(object sender, EventArgs e)
        {
            DocumentManager.SaveAllFiles();
        }

        private void dockPanel_ContentRemoved(object sender, DockContentEventArgs e)
        {
            if (dockPanel.ActiveDocument == null) DeactivateEditControls();
        }

        private void DeactivateEditControls()
        {
            undoToolStripMenuItem.Enabled = false;
            redoToolStripMenuItem.Enabled = false;
            toolStripButtonUndo.Enabled = false;
            toolStripButtonRedo.Enabled = false;
        }

        private void toolStripButtonCompileAndRun_Click(object sender, EventArgs e)
        {
            CompileAndRun();
        }

        private void formMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            WindowManager.SaveLayout();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var aboutBox = new AboutBox();
            aboutBox.ShowDialog();
        }

        private void compileAndRunToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CompileAndRun();
        }

        private void solutionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SolutionManager.SolutionManager.LoadSolution();
        }

        private void exitAndElevateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplicationManager.ExitAndElevate();
        }

        private void formMain_Deactivate(object sender, EventArgs e)
        {
            ApplicationManager.SetWorkingSet();
        }

        private void contentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (
                MessageBox.Show(
                    "The application doesn't currently have a help system. Would you like to go to \"http://vpbide.codeplex.com/Thread/List.aspx\" now?",
                    "Help system is not implemented", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) !=
                DialogResult.Yes) return;

            Process.Start("http://vpbide.codeplex.com/Thread/List.aspx");
        }
        #endregion
    }
}